package roborally.program.commands;

import be.kuleuven.cs.som.annotate.*;
import roborally.model.Direction;
import roborally.model.Robot;

/**
 * A class for dealing with turn-commands: (turn clockwise) or (turn counter-clockwise).     
 * 
 * @invar	The direction of each turn-command must be valid.
 * 			| canHaveAsDirection(getDirection())
 * 
 * @version	1.0
 * @author  Pieter Robberechts	(1e Bach Informatica)
 * @author	Jeroen Sanders		(1e Bach Informatica)
 *
 */
public class Turn extends BasicCommand {

	/**
	 * Initialize this new turn-command with a line number an direction.
	 * 
	 * @param 	direction
	 * 			The direction associated with this turn-command.
	 * @pre		The given direction must be a valid one.
	 * 			| canHaveAsDirection(direction)
	 * @post	The direction of this turn-command is set to the given direction.
	 * 			| new.getDirection() == direction
	 */
	public Turn(int lineNb, Direction direction) {
		super(lineNb);
		assert(canHaveAsDirection(direction));
		this.direction = direction;
	}
	
	/**
	 * Variable registering the direction associated with this turn-command.
	 */
	private final Direction direction;
	
	/**
	 * Return the direction associated with this turn-command.
	 */
	@Basic @Raw @Immutable
	public Direction getDirection() {
		return direction;
	}
	
	/**
	 * Check whether the given direction is a valid direction for a turn-command.
	 * 
	 * @param 	direction
	 * 			The direction to check for whether it is a valid one.
	 * @return	Return true if and only if the given direction is 'clockwise' or
	 * 			'counter-clockwise'; else return false.
	 * 			| result == ( direction == Direction.CLOCKWISE || 
	 * 			|				direction == Direction.COUNTER_CLOCKWISE )
	 */
	@Raw
	public boolean canHaveAsDirection(Direction direction) {
		return ( direction == Direction.CLOCKWISE || 
					direction == Direction.COUNTER_CLOCKWISE );
	}

	/**
	 * Return a textual representation of this turn-command,
	 * formatted in accordance with its position in the program.
	 * 
	 * @return	The result is a pretty formatted string of this turn-command,
	 * 			taking in account his relative position in the program.
	 * 			| if(getDirection() == Direction.CLOCKWISE)
	 * 			| 	then result == getIndentation(indentationLevel) + "(turn clockwise)"
	 * 			| if(getDirection() == Direction.COUNTER_CLOCKWISE)
	 * 			| 	then result == getIndentation(indentationLevel) + "(turn counter-clockwise)"
	 */
	@Override
	public String prettyFormat(int indentationLevel) {
		if(getDirection() == Direction.CLOCKWISE)
			return getIndentation(indentationLevel) + "(turn clockwise)";
		return getIndentation(indentationLevel) + "(turn counter-clockwise)"; 
	}

	/**
	 * Execute the turn-command on the given robot.
	 * 
	 * @effect	The given robot turns in the direction associated with this turn-command.
	 * 			| robot.turn(getDirection())
	 */
	@Override
	public void execute(Robot robot) throws IllegalArgumentException {
		super.execute(robot);
		robot.turn(getDirection());		
	}
	
}
